package kit.core;

import java.text.DecimalFormat;

/**
 * Gli oggetti di classe {@link Challenge} rappresentano le verifiche eseguibili
 * tramite l'algoritmo descritto nell'articolo di Carl M. Ellison.
 * 
 * @author mattia
 */
public class Challenge {
	/**
	 * Numero di fallimenti massimi durante la verifica. Impostato manualmente
	 * dall'utente.
	 */
	private int maxRound;

	/**
	 * Numero di fallimenti avvenuti.
	 */
	private int failures;

	/**
	 * Iterazioni effettuate.
	 */
	private int rounds;

	/**
	 * Valore dell'entropia accumulata durante la verifica.
	 */
	private double entropy;

	/**
	 * Valore d'entropia corrispondente al successo della verifica. Il valore è
	 * dato da min(|K|,|H|), dove |K| e |H| rappresentano il parametro di
	 * sicurezza rispettivamente dell'algoritmo a chiave pubblica e della
	 * funzione di hash utilizzata.
	 */
	private double entropyLimit;

	/**
	 * ID dell'utente locale, nel formato GPG.
	 */
	private String localUID;
	/**
	 * ID dell'utente remoto, nel formato GPG.
	 */
	private String receiverUID;

	/**
	 * @param nRound
	 *            Massimo numero di fallimenti consentiti.
	 * @param localUID
	 *            Utente GPG locale.
	 * @param receiverUID
	 *            Utente GPG remoto, del quale si vuole verificare l'identità.
	 */
	public Challenge(int nRound, String localUID, String receiverUID,
			double entropyLimit) {
		this.maxRound = nRound;
		this.localUID = localUID;
		this.receiverUID = receiverUID;
		this.entropyLimit = entropyLimit;
	}

	/**
	 * Incremento del punteggio di entropia raggiunto.
	 * 
	 * @param entropy
	 *            Incremento.
	 */
	public void concludeRound(double inputEntropy) {
		this.entropy += Math.min(inputEntropy, Core.obtainSingleton()
				.calculateRoundEntropy());
		rounds++;
	}

	/**
	 * Utilizzato per rappresentare nella GUI lo stato della verifica.
	 */
	@Override
	public String toString() {
		DecimalFormat df = new DecimalFormat("#.#####");
		String result = String
				.format("Entropia: %s su %s\nRound [Falliti/Massimo/Totali]: %s/%s/%s\n",
						df.format(entropy), entropyLimit, failures, maxRound,
						rounds);
		return result;
	}

	public double getEntropy() {
		return entropy;
	}

	public void setEntropyLimit(double entropyLimit) {
		this.entropyLimit = entropyLimit;
	}

	public double getEntropyLimit() {
		return entropyLimit;
	}

	public void fail() {
		failures++;
		rounds++;
	}

	public boolean isMaxFailuresLimitReached() {
		return failures >= maxRound;
	}

	public String getLocalUID() {
		return localUID;
	}

	public String getReceiverUID() {
		return receiverUID;
	}

	public void setLocalUID(String localUID) {
		this.localUID = localUID;
	}

	public void setReceiverUID(String receiverUID) {
		this.receiverUID = receiverUID;
	}

}
